home *** CD-ROM | disk | FTP | other *** search
- /*
- tee-handler.c
-
- This is a `T' pipe for AmigaDOS. Now, for example, you can display
- the shell output of a program in a console window and, at the
- same time, capture it into a file.
-
-
- This stuff is explicitly declared as Public Domain.
- 07-Sep-96 by Michael Krause <rawstyle@blackbox.dame.de>
- */
-
- #include <exec/exec.h>
- #include <dos/dos.h>
- #include <dos/filehandler.h>
-
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- char verstring[] = "$VER: tee-handler v1.0 (7.9.96)";
-
- static struct DosLibrary *DOSBase;
- static struct ExecBase *SysBase;
-
- static char colonchar='%', divchar='@';
-
- struct fharg1
- {
- ULONG count;
- BPTR fh[1];
- };
-
- static void ReturnPacket(struct DosPacket *, struct MsgPort *, LONG, LONG);
- static struct DosPacket *GetPacket(struct MsgPort *);
- static STRPTR where(STRPTR, char);
- static void strncpy(STRPTR, STRPTR, UWORD);
- static void replace(STRPTR);
-
- /*----------------- THE ENTRY POINT ------------------------------------*/
-
- void entry(void)
- {
- struct MsgPort *procport, *packetport;
- struct DosPacket *packet;
- struct DeviceNode *devnode;
- LONG error=0, err2;
- ULONG i;
- STRPTR names, name1, name2;
- struct fharg1 *thisfharg1;
- BPTR fh;
-
- SysBase = *(APTR*)4;
-
- procport = &((struct Process *)FindTask(NULL))->pr_MsgPort;
- WaitPort(procport);
- packet = GetPacket(procport);
-
- if(DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME, 36))
- {
- /* We need a new MsgPort because the "built-in" one would interfer
- with our dos.library calls. */
- if(packetport = CreateMsgPort())
- {
- devnode = (struct DeviceNode *)BADDR(packet->dp_Arg3);
- packet->dp_Arg4 = (LONG) packetport;
- devnode->dn_Task = packetport;
- ReturnPacket(packet, packetport, DOSTRUE, 0);
-
- /* Handler initialized, now process messages */
- for(;;)
- {
- WaitPort(packetport);
- packet=GetPacket(packetport);
- switch(packet->dp_Type)
- {
- case ACTION_FINDOUTPUT:
- err2 = ERROR_NO_FREE_STORE;
-
- /* First copy the BSTR into a private buffer */
- name1 = (STRPTR)BADDR(packet->dp_Arg3);
- if(names = (STRPTR)AllocVec((*name1)+1, MEMF_ANY))
- {
- strncpy(names, name1+1, *name1);
-
- /* Count destination files */
- name1 = where(names, ':');
- i = 1;
- while((name2=where(name1,divchar))!=name1)
- {
- name1 = name2;
- i++;
- }
-
- /* Get private data space */
- if(thisfharg1 = (struct fharg1 *)AllocMem(4*i+1, MEMF_CLEAR))
- {
- thisfharg1->count = i;
-
- err2 = ERROR_INVALID_COMPONENT_NAME;
-
- /* Open destination files */
- name1 = where(names, ':');
- for(i=0;i<thisfharg1->count;i++)
- {
- name2 = where(name1, divchar);
- if(name2 != name1)
- name2[-1] = '\0'; /* Terminate string (replace divchar by \0) */
- replace(name1);
-
- if(where(name1, ':') == name1) /* Require an absolute path */
- break;
- if(!(thisfharg1->fh[i] = Open(name1, MODE_NEWFILE)))
- break;
- name1 = name2;
- }
-
- if(i==thisfharg1->count)
- {
- /* Now all files successfully opened. */
- fh = (BPTR)BADDR(packet->dp_Arg1);
- ((struct FileHandle *)fh)->fh_Arg1 = (LONG)thisfharg1;
- ((struct FileHandle *)fh)->fh_Port = DOSFALSE;
- FreeVec(names);
- ReturnPacket(packet, packetport, DOSTRUE, 0);
- break;
- }
-
- for(i=0;i<thisfharg1->count;i++)
- if(fh=thisfharg1->fh[i])
- Close(fh);
- FreeMem(thisfharg1, 4*i+1);
- }
- FreeVec(names);
- }
-
- ReturnPacket(packet, packetport, DOSFALSE, err2);
- break;
-
- case ACTION_WRITE:
- thisfharg1 = (struct fharg1 *)packet->dp_Arg1;
- for(i=0;i<thisfharg1->count;i++)
- Write(thisfharg1->fh[i], (APTR)packet->dp_Arg2, packet->dp_Arg3);
- ReturnPacket(packet, packetport, packet->dp_Arg3, 0);
- break;
-
- case ACTION_END:
- thisfharg1 = (struct fharg1 *)packet->dp_Arg1;
- for(i=0;i<thisfharg1->count;i++)
- Close(thisfharg1->fh[i]);
- FreeMem(thisfharg1, 4*i+1);
- ReturnPacket(packet, packetport, DOSTRUE, 0);
- /* This was easy, hmm? */
- break;
-
- default:
- ReturnPacket(packet, packetport, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
- break;
- }
- }
-
- devnode->dn_Task=NULL;
- }
- else error = ERROR_NO_FREE_STORE;
- CloseLibrary((struct Library*)DOSBase);
- }
- else error = ERROR_OBJECT_NOT_FOUND;
-
- if(error)
- ReturnPacket(packet, procport, DOSFALSE, error);
- }
-
- /*----------------- SUBROUTINES ----------------------------------------*/
-
- void ReturnPacket(struct DosPacket *packet, struct MsgPort *port, LONG res1, LONG res2)
- {
- struct MsgPort *mp = packet->dp_Port;
-
- packet->dp_Port = port;
- packet->dp_Res1 = res1;
- packet->dp_Res2 = res2;
-
- PutMsg(mp, packet->dp_Link);
- }
-
- struct DosPacket *GetPacket(struct MsgPort *port)
- {
- struct Message *msg;
-
- if(msg = GetMsg(port))
- return((struct DosPacket *)msg->mn_Node.ln_Name);
- else
- return(NULL);
- }
-
- /* Find character in string and return address of first occurence + 1,
- if not found, return full string */
- STRPTR where(STRPTR s, char x)
- {
- char a,i=0;
-
- while(a=s[i++])
- if(a==x) return(&s[i]);
-
- return(s);
- }
-
- void strncpy(STRPTR a, STRPTR b, UWORD c)
- {
- for(;;)
- {
- if((WORD)--c<0) break;
- *a++ = *b++;
- }
- *a = '\0';
- }
-
- /* Replace first colonchar with colon */
- void replace(STRPTR s)
- {
- char c;
-
- while(c=*s++)
- if(c==colonchar)
- {
- s[-1]=':';
- return;
- }
- }
-